import re
from pathlib import Path

from scheduling_environment.job import Job
from scheduling_environment.machine import Machine
from scheduling_environment.operation import Operation


def parse_fjsp(JobShop, instance, from_absolute_path=False):
    """
    解析柔性作业车间实例。

    参数:
        JobShop: 用于加载解析数据的 JobShop 对象。
        instance: 实例文件的名称或路径。
        from_absolute_path: 布尔值，如果为 True，则表示 'instance' 是绝对路径。

    返回:
        加载了实例数据的 JobShop 对象。
    """

    # 设置 JobShop 对象的实例名称
    JobShop.set_instance_name(instance)

    # 确定实例数据文件的路径
    if not from_absolute_path:
        base_path = Path(__file__).parent.parent.absolute()
        data_path = base_path.joinpath('data' + instance)
    else:
        data_path = instance

    with open(data_path, "r") as data:
        # 读取并解析第一行，获取总任务数、总机器数和最大操作数
        total_jobs, total_machines, max_operations = re.findall('\S+', data.readline())
        number_total_jobs, number_total_machines, number_max_operations = int(total_jobs), int(total_machines), int(float(max_operations))

        # 设置 JobShop 的任务数和机器数
        JobShop.set_nr_of_jobs(number_total_jobs)
        JobShop.set_nr_of_machines(number_total_machines)

        precedence_relations = {}
        job_id = 0
        operation_id = 0

        optional_machines_num = [] # 存储  操作可选机器的个数

        # 遍历数据文件中的每一行，解析每个任务的数据
        for key, line in enumerate(data):
            if key >= number_total_jobs:
                break

            # 按多个空格分隔符拆分数据行
            parsed_line = re.findall('\S+', line)

            i = 1
            job = Job(job_id)

            while i < len(parsed_line):
                # 当前操作的操作选项总数
                operation_options = int(parsed_line[i])

                # 存储  操作可选机器的个数
                optional_machines_num.append(operation_options)

                # 创建当前操作对象
                operation = Operation(job, job_id, operation_id)

                for operation_options_id in range(operation_options):
                    machine_id = int(parsed_line[i + 1 + 2 * operation_options_id]) - 1
                    duration = int(parsed_line[i + 2 + 2 * operation_options_id])
                    operation.add_operation_option(machine_id, duration)

                job.add_operation(operation)
                JobShop.add_operation(operation)

                if i != 1:
                    precedence_relations[operation_id] = [JobShop.get_operation(operation_id - 1)]

                i += 1 + 2 * operation_options
                operation_id += 1

            JobShop.add_job(job)
            job_id += 1

        # 设置 JobShop 的操作可选机器的个数
        JobShop.set_operations_machine_num(optional_machines_num)

    # 将没有前置操作的操作添加到前置关系字典中
    for operation in JobShop.operations:
        if operation.operation_id not in precedence_relations.keys():
            precedence_relations[operation.operation_id] = []
        operation.add_predecessors(precedence_relations[operation.operation_id])

    # 初始化序列依赖设置时间矩阵
    sequence_dependent_setup_times = [[[0 for r in range(len(JobShop.operations))] for t in range(len(JobShop.operations))] for m in range(number_total_machines)]

    # 添加前置关系和序列依赖设置时间
    JobShop.add_precedence_relations_operations(precedence_relations)
    JobShop.add_sequence_dependent_setup_times(sequence_dependent_setup_times)

    # 添加机器
    for id_machine in range(0, number_total_machines):
        JobShop.add_machine(Machine(id_machine))

    return JobShop



# if __name__ == "__main__":
#     from scheduling_environment.jobShop import JobShop
#     jobShopEnv = JobShop()
#     jobShopEnv = parse_fjsp(jobShopEnv, '/fjsp/1_brandimarte/Mk01.fjs')
#     jobShopEnv.update_operations_available_for_scheduling()
#     print(jobShopEnv.operations_available_for_scheduling)